#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
文件名称: generate_comprehensive_test_data.py
完整存储路径: scripts/generate_comprehensive_test_data.py
功能说明:
    为近视预防干预系统生成60名学生的完整测试数据
    包括学生档案、视力记录、干预操作、随访记录等所有核心数据
    数据分配给三个学校，每校20名学生，具有真实性和完整性
    
使用说明:
    python scripts/generate_comprehensive_test_data.py
    
学校教育ID规则:
    - 101: 苏宁红军小学 (1010001-1010020)
    - 102: 华兴小学 (1020001-1020020)  
    - 103: 大附小清华小学 (1030001-1030020)
"""

import sys
import os
from datetime import datetime, date, time, timedelta
import random
from faker import Faker

# 添加项目根目录到Python路径
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, project_root)

from backend import create_app
from backend.infrastructure.database import db
from backend.models.student import Student
from backend.models.vision import VisionRecord
from backend.models.intervention import InterventionRecord
from backend.models.followup import FollowupRecord

# 初始化Faker，设置中文语言
fake = Faker('zh_CN')

class TestDataGenerator:
    """测试数据生成器"""
    
    def __init__(self):
        """初始化生成器"""
        # 学校配置
        self.schools = {
            101: "苏宁红军小学",
            102: "华兴小学", 
            103: "大附小清华小学"
        }
        
        # 班级配置
        self.classes = ["一年级1班", "一年级2班", "二年级1班", "二年级2班", 
                       "三年级1班", "三年级2班", "四年级1班", "四年级2班",
                       "五年级1班", "五年级2班", "六年级1班", "六年级2班"]
        
        # 基础手机号，按顺序递增（符合验证规则）
        self.base_phone = 13800000000
        
        # 干预类型配置
        self.intervention_types = [
            "耳穴压丸", "刮痧", "艾灸", "中药熏蒸", 
            "热灸训练", "热磁脉冲", "拔罐"
        ]
        
        # 随访类型配置
        self.followup_types = [
            "定期随访", "症状随访", "治疗随访", "康复随访"
        ]
        
        # 穴位选择
        self.acupoints = [
            "眼", "肝", "肾", "神门", "内分泌", "皮质下", 
            "枕", "额", "太阳", "风池", "睛明", "攒竹"
        ]
        
        # 操作医生名单
        self.doctors = [
            "王医生", "李医生", "张医生", "刘医生", "陈医生",
            "杨医生", "黄医生", "赵医生", "周医生", "吴医生"
        ]
        
        print("✅ 测试数据生成器初始化完成")
    
    def generate_education_id(self, school_code, student_number):
        """生成教育ID
        Args:
            school_code: 学校代码 (101, 102, 103)
            student_number: 学生编号 (1-20)
        Returns:
            str: 教育ID，格式如 "1010001"
        """
        return f"{school_code}{student_number:04d}"
    
    def generate_student_data(self, school_code, student_number):
        """生成单个学生的基本档案数据
        
        Args:
            school_code: 学校代码
            student_number: 学生编号
            
        Returns:
            dict: 学生数据字典
        """
        education_id = self.generate_education_id(school_code, student_number)
        school_name = self.schools[school_code]
        
        # 生成真实的姓名
        name = fake.name()
        
        # 随机性别
        gender = random.choice(["男", "女"])
        
        # 生成出生日期（6-12岁的小学生）
        age = random.randint(6, 12)
        birthday = fake.date_between(
            start_date=date.today() - timedelta(days=age*365+365),
            end_date=date.today() - timedelta(days=age*365)
        )
        
        # 递增的家长手机号
        parent_phone_num = self.base_phone + (school_code - 101) * 20 + student_number - 1
        parent_phone = str(parent_phone_num)
        
        # 学生联系电话（可能没有）
        student_phone = parent_phone if random.random() > 0.7 else None
        
        # 生成身份证号（伪造但格式正确）
        id_card = fake.ssn() if random.random() > 0.3 else None
        
        # 地址信息
        region = fake.district()
        contact_address = fake.address()
        
        # 家长姓名
        parent_name = fake.name()
        
        # 随机班级
        class_name = random.choice(self.classes)
        
        return {
            "education_id": education_id,
            "school": school_name,
            "class_name": class_name,
            "name": name,
            "gender": gender,
            "birthday": birthday,
            "phone": student_phone,
            "id_card": id_card,
            "region": region,
            "contact_address": contact_address,
            "parent_name": parent_name,
            "parent_phone": parent_phone
        }
    
    def generate_vision_record(self, student_id, record_number):
        """生成视力记录数据
        
        Args:
            student_id: 学生ID
            record_number: 记录编号 (1或2)
            
        Returns:
            dict: 视力记录数据
        """
        # 第一条记录是基线数据，第二条是随访数据
        is_baseline = (record_number == 1)
        
        # 测量日期（基线数据较早，随访数据较晚）
        days_ago = 180 if is_baseline else 60
        measure_date = fake.date_between(
            start_date=date.today() - timedelta(days=days_ago+30),
            end_date=date.today() - timedelta(days=days_ago-30)
        )
        
        # 生成视力数据（模拟真实情况）
        # 基线数据相对较差，随访数据可能有改善
        base_vision_left = random.uniform(3.8, 5.2)
        base_vision_right = random.uniform(3.8, 5.2)
        
        if not is_baseline:
            # 随访数据可能有轻微改善
            improvement = random.uniform(-0.1, 0.3)
            base_vision_left += improvement
            base_vision_right += improvement
        
        # 屈光度数据（近视度数）
        left_sphere = round(random.uniform(-6.0, 0.5), 2)
        right_sphere = round(random.uniform(-6.0, 0.5), 2)
        left_cylinder = round(random.uniform(-2.0, 0), 2) if random.random() > 0.6 else None
        right_cylinder = round(random.uniform(-2.0, 0), 2) if random.random() > 0.6 else None
        
        # 轴位（有柱镜时才有）
        left_axis = round(random.uniform(0, 180), 1) if left_cylinder else None
        right_axis = round(random.uniform(0, 180), 1) if right_cylinder else None
        
        # 矫正视力通常比裸眼视力好
        left_corrected = min(5.3, base_vision_left + random.uniform(0, 1.0))
        right_corrected = min(5.3, base_vision_right + random.uniform(0, 1.0))
        
        # 眼轴长度（近视眼通常较长）
        left_axial = round(random.uniform(22.0, 26.5), 2)
        right_axial = round(random.uniform(22.0, 26.5), 2)
        
        return {
            "student_id": student_id,
            "measure_date": measure_date,
            "measure_time": fake.time(),
            "measure_location": f"{self.schools[101]}视力检查室",  # 简化处理
            "measure_type": "基线数据" if is_baseline else "随访数据",
            "measurer": random.choice(self.doctors),
            "is_baseline": is_baseline,
            "measurement_sequence": record_number,
            "data_year": str(measure_date.year),
            "left_eye_naked": round(base_vision_left, 1),
            "right_eye_naked": round(base_vision_right, 1),
            "left_eye_corrected": round(left_corrected, 1),
            "right_eye_corrected": round(right_corrected, 1),
            "left_sphere": left_sphere,
            "right_sphere": right_sphere,
            "left_cylinder": left_cylinder,
            "right_cylinder": right_cylinder,
            "left_axis": left_axis,
            "right_axis": right_axis,
            "left_axial_length": left_axial,
            "right_axial_length": right_axial,
            "left_keratometry_K1": round(random.uniform(40.0, 46.0), 2),
            "right_keratometry_K1": round(random.uniform(40.0, 46.0), 2),
            "left_keratometry_K2": round(random.uniform(40.0, 46.0), 2),
            "right_keratometry_K2": round(random.uniform(40.0, 46.0), 2)
        }
    
    def generate_intervention_record(self, student_id, record_number):
        """生成干预操作记录数据
        
        Args:
            student_id: 学生ID  
            record_number: 记录编号 (1或2)
            
        Returns:
            dict: 干预记录数据
        """
        # 干预日期
        days_ago = 120 if record_number == 1 else 45
        intervention_date = fake.date_between(
            start_date=date.today() - timedelta(days=days_ago+15),
            end_date=date.today() - timedelta(days=days_ago-15)
        )
        
        # 随机选择干预类型
        intervention_type = random.choice(self.intervention_types)
        
        # 操作详情
        is_home = random.random() > 0.6  # 40%是医院干预，60%是家庭干预
        
        # 选择穴位（耳穴压丸特有）
        selected_acupoints = random.sample(self.acupoints, random.randint(3, 6))
        
        # 家长关系
        parent_relations = ["父亲", "母亲", "爷爷", "奶奶", "外公", "外婆"]
        
        data = {
            "student_id": student_id,
            "intervention_date": intervention_date,
            "operation_time": fake.time(),
            "intervention_type": intervention_type,
            "operator": random.choice(self.doctors),
            "duration_minutes": random.randint(15, 60),
            "operation_location": "家中" if is_home else f"{self.schools[101]}治疗室",
            "data_year": str(intervention_date.year),
            "is_home_intervention": is_home,
            "session_number": record_number,
            "immediate_effect": random.choice(["有效", "无效", "待观察"]),
            "cooperation_level": random.choice(["良好", "一般", "较差"]),
            "details": f"第{record_number}次{intervention_type}干预操作，患者配合良好。"
        }
        
        # 家庭干预特有字段
        if is_home:
            data.update({
                "home_operator": fake.name(),
                "home_operator_relation": random.choice(parent_relations),
                "home_intervention_day": random.randint(1, 30),
                "daily_frequency": random.randint(1, 3),
                "parent_feedback": "孩子配合度良好，未出现不适反应。",
                "upload_source": "小程序"
            })
        
        # 耳穴压丸特有字段
        if intervention_type == "耳穴压丸":
            data.update({
                "acupoints": selected_acupoints,
                "press_methods": ["王不留行籽", "磁珠"],
                "press_strength": random.choice(["轻度", "中度", "重度"]),
                "press_frequency": random.randint(30, 60)
            })
        
        # 刮痧特有字段
        elif intervention_type == "刮痧":
            data.update({
                "scraping_intensity": random.choice(["轻度", "中度", "重度"]),
                "scraping_direction": random.choice(["顺经", "逆经", "横向"]),
                "scraping_duration": random.randint(10, 30),
                "skin_reaction": random.choice(["红润", "紫红", "瘀斑"])
            })
        
        # 艾灸特有字段  
        elif intervention_type == "艾灸":
            data.update({
                "moxibustion_type": random.choice(["直接灸", "间接灸", "温和灸"]),
                "temperature_level": random.choice(["温热", "微热", "灼热"]),
                "moxibustion_distance": random.choice(["近距", "中距", "远距"])
            })
        
        return data
    
    def generate_followup_record(self, student_id, record_number):
        """生成随访记录数据
        
        Args:
            student_id: 学生ID
            record_number: 记录编号 (1或2)
            
        Returns:
            dict: 随访记录数据
        """
        # 随访日期
        days_ago = 90 if record_number == 1 else 30
        followup_date = fake.date_between(
            start_date=date.today() - timedelta(days=days_ago+10),
            end_date=date.today() - timedelta(days=days_ago-10)
        )
        
        # 随访基本信息
        interviewee_relations = ["父亲", "母亲", "爷爷", "奶奶", "外公", "外婆", "本人"]
        contact_methods = ["电话", "微信", "面访", "视频通话"]
        
        # 评价选项
        satisfaction_options = ["非常满意", "满意", "一般", "不满意"]
        effect_options = ["显著改善", "有所改善", "无明显变化", "有所恶化"]
        compliance_options = ["完全依从", "基本依从", "部分依从", "不依从"]
        vision_change_options = ["明显改善", "稍有改善", "无变化", "有所下降"]
        
        return {
            "student_id": student_id,
            "followup_date": followup_date,
            "followup_time": fake.time(),
            "interviewer": random.choice(self.doctors),
            "interviewee": fake.name(),
            "interviewee_relation": random.choice(interviewee_relations),
            "contact_method": random.choice(contact_methods),
            "followup_duration": random.randint(10, 30),
            "followup_type": random.choice(self.followup_types),
            "intervention_satisfaction": random.choice(satisfaction_options),
            "intervention_effect_evaluation": random.choice(effect_options),
            "intervention_compliance": random.choice(compliance_options),
            "side_effects": "无明显不良反应" if random.random() > 0.1 else "偶有轻微不适",
            "vision_change_perception": random.choice(vision_change_options),
            "vision_improvement_details": f"第{record_number}次随访，家长反馈孩子视力情况稳定。",
            "vision_concern_areas": "担心近视度数继续增加",
            "daily_eye_use_time": f"每日用眼约{random.randint(4, 8)}小时",
            "content": f"第{record_number}次电话随访，了解干预治疗效果和视力变化情况。",
            "feedback": "家长配合度高，希望继续治疗。",
            "data_year": str(followup_date.year)
        }
    
    def create_students(self):
        """创建60名学生的基本档案"""
        students = []
        print("\n🏫 开始创建学生档案...")
        
        for school_code in [101, 102, 103]:
            school_name = self.schools[school_code]
            print(f"  📚 创建 {school_name} 学生档案...")
            
            for student_num in range(1, 21):  # 每校20名学生
                student_data = self.generate_student_data(school_code, student_num)
                student = Student(**student_data)
                db.session.add(student)
                students.append(student)
                
                if student_num % 5 == 0:  # 每5个学生显示一次进度
                    print(f"    ✅ 已创建 {student_num}/20 名学生")
        
        # 批量提交学生数据
        try:
            db.session.commit()
            print(f"✅ 成功创建 {len(students)} 名学生档案")
            return students
        except Exception as e:
            db.session.rollback()
            print(f"❌ 创建学生档案失败: {str(e)}")
            raise
    
    def create_vision_records(self, students):
        """为每个学生创建2条视力记录"""
        print("\n👁️ 开始创建视力记录...")
        
        total_records = 0
        for i, student in enumerate(students):
            for record_num in range(1, 3):  # 每人2条记录
                vision_data = self.generate_vision_record(student.id, record_num)
                vision_record = VisionRecord(**vision_data)
                db.session.add(vision_record)
                total_records += 1
            
            if (i + 1) % 10 == 0:  # 每10个学生显示一次进度
                print(f"  ✅ 已为 {i + 1}/{len(students)} 名学生创建视力记录")
        
        try:
            db.session.commit()
            print(f"✅ 成功创建 {total_records} 条视力记录")
        except Exception as e:
            db.session.rollback()
            print(f"❌ 创建视力记录失败: {str(e)}")
            raise
    
    def create_intervention_records(self, students):
        """为每个学生创建2条干预记录"""
        print("\n🏥 开始创建干预记录...")
        
        total_records = 0
        for i, student in enumerate(students):
            for record_num in range(1, 3):  # 每人2条记录
                intervention_data = self.generate_intervention_record(student.id, record_num)
                intervention_record = InterventionRecord(**intervention_data)
                db.session.add(intervention_record)
                total_records += 1
            
            if (i + 1) % 10 == 0:  # 每10个学生显示一次进度
                print(f"  ✅ 已为 {i + 1}/{len(students)} 名学生创建干预记录")
        
        try:
            db.session.commit()
            print(f"✅ 成功创建 {total_records} 条干预记录")
        except Exception as e:
            db.session.rollback()
            print(f"❌ 创建干预记录失败: {str(e)}")
            raise
    
    def create_followup_records(self, students):
        """为每个学生创建2条随访记录"""
        print("\n📞 开始创建随访记录...")
        
        total_records = 0
        for i, student in enumerate(students):
            for record_num in range(1, 3):  # 每人2条记录
                followup_data = self.generate_followup_record(student.id, record_num)
                followup_record = FollowupRecord(**followup_data)
                db.session.add(followup_record)
                total_records += 1
            
            if (i + 1) % 10 == 0:  # 每10个学生显示一次进度
                print(f"  ✅ 已为 {i + 1}/{len(students)} 名学生创建随访记录")
        
        try:
            db.session.commit()
            print(f"✅ 成功创建 {total_records} 条随访记录")
        except Exception as e:
            db.session.rollback()
            print(f"❌ 创建随访记录失败: {str(e)}")
            raise
    
    def generate_all_test_data(self):
        """生成所有测试数据"""
        print("🚀 开始生成60名学生的完整测试数据")
        print("=" * 60)
        
        try:
            # 1. 创建学生档案
            students = self.create_students()
            
            # 2. 创建视力记录
            self.create_vision_records(students)
            
            # 3. 创建干预记录
            self.create_intervention_records(students)
            
            # 4. 创建随访记录
            self.create_followup_records(students)
            
            print("\n" + "=" * 60)
            print("🎉 测试数据生成完成！")
            print(f"📊 数据统计:")
            print(f"   👥 学生档案: {len(students)} 名")
            print(f"   👁️ 视力记录: {len(students) * 2} 条")
            print(f"   🏥 干预记录: {len(students) * 2} 条")
            print(f"   📞 随访记录: {len(students) * 2} 条")
            print(f"   📈 总记录数: {len(students) * 7} 条")
            
            # 显示学校分布
            print(f"\n🏫 学校分布:")
            for school_code, school_name in self.schools.items():
                print(f"   {school_name}: 20名学生 (教育ID: {school_code}0001-{school_code}0020)")
            
            print(f"\n📱 家长手机号范围: {self.base_phone} - {self.base_phone + 59}")
            print("✅ 所有数据已成功写入数据库，可用于系统全面测试！")
            
        except Exception as e:
            print(f"❌ 数据生成过程中出现错误: {str(e)}")
            db.session.rollback()
            raise

def main():
    """主函数"""
    print("🔧 近视预防干预系统 - 综合测试数据生成器")
    print("=" * 60)
    
    # 创建Flask应用和数据库上下文
    app = create_app()
    
    with app.app_context():
        # 检查数据库连接
        try:
            db.engine.execute('SELECT 1')
            print("✅ 数据库连接正常")
        except Exception as e:
            print(f"❌ 数据库连接失败: {str(e)}")
            return
        
        # 检查是否已有测试数据
        existing_students = Student.query.filter(
            Student.education_id.like('101%') | 
            Student.education_id.like('102%') | 
            Student.education_id.like('103%')
        ).count()
        
        if existing_students > 0:
            print(f"⚠️ 检测到已存在 {existing_students} 条相关测试数据")
            response = input("是否清除现有数据并重新生成？(y/N): ")
            if response.lower() != 'y':
                print("❌ 操作已取消")
                return
            
            # 清除现有测试数据
            print("🗑️ 正在清除现有测试数据...")
            try:
                # 由于外键约束，需要按顺序删除
                db.session.query(FollowupRecord).filter(
                    FollowupRecord.student_id.in_(
                        db.session.query(Student.id).filter(
                            Student.education_id.like('101%') | 
                            Student.education_id.like('102%') | 
                            Student.education_id.like('103%')
                        )
                    )
                ).delete(synchronize_session=False)
                
                db.session.query(InterventionRecord).filter(
                    InterventionRecord.student_id.in_(
                        db.session.query(Student.id).filter(
                            Student.education_id.like('101%') | 
                            Student.education_id.like('102%') | 
                            Student.education_id.like('103%')
                        )
                    )
                ).delete(synchronize_session=False)
                
                db.session.query(VisionRecord).filter(
                    VisionRecord.student_id.in_(
                        db.session.query(Student.id).filter(
                            Student.education_id.like('101%') | 
                            Student.education_id.like('102%') | 
                            Student.education_id.like('103%')
                        )
                    )
                ).delete(synchronize_session=False)
                
                db.session.query(Student).filter(
                    Student.education_id.like('101%') | 
                    Student.education_id.like('102%') | 
                    Student.education_id.like('103%')
                ).delete(synchronize_session=False)
                
                db.session.commit()
                print("✅ 现有测试数据已清除")
                
            except Exception as e:
                db.session.rollback()
                print(f"❌ 清除数据失败: {str(e)}")
                return
        
        # 生成新的测试数据
        generator = TestDataGenerator()
        generator.generate_all_test_data()

if __name__ == "__main__":
    main()
